#define _DEFAULT_SOURCE
#include "app_device.h"
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include "log/log.h"
#include "app_pool.h"
#include "app_common.h"

#define BUFFER_SIZE 1024

Device *app_device_init(char *filename)
{
    Device *device = (Device *)malloc(sizeof(Device));
    device->fd = open(filename, O_RDWR|O_NOCTTY);
    if (device->fd < 0) {
        log_warn("open %s failed", filename);
        return NULL;
    }
    device->name = filename;
    device->type = GENERAL;
    device->conn_type = CONN_NONE;
    device->last_write_time = 0;
   
    device->funcs = malloc(sizeof(DeviceFuncs));
    if (device->funcs == NULL)
    {
        LOGE("malloc vptr failed");
        app_device_close(device);
        return NULL;
    }
    device->read_buffer = app_buffer_init(BUFFER_SIZE);
    if (device->read_buffer == NULL)
    {
        LOGE("malloc read_buffer failed");
        app_device_close(device);
        return NULL;
    }
    device->write_buffer = app_buffer_init(BUFFER_SIZE);
    if (device->write_buffer == NULL)
    {
        LOGE("malloc write_buffer failed");
        app_device_close(device);
        return NULL;
    }
    
    return device;
}

int app_device_start(Device *device)
{
    device->running = 1;
    if (pthread_create(&device->read_thread, NULL, app_device_read, device) != 0)
    {
        device->running = 0;
        return -1;
    }
    return 0;
}

int app_device_stop(Device *device)
{
    if (device->running > 0)
    {
        device->running = 0;
        pthread_cancel(device->read_thread);
        pthread_join(device->read_thread, NULL);
    }
}

void app_device_close(Device *device)
{
    if (device->funcs)
    {
        free(device->funcs);
    }
    if (device->read_buffer)
    {
        app_buffer_free(device->read_buffer);
    }
    if (device->write_buffer)
    {
        app_buffer_free(device->write_buffer);
    }
    if (device->fd > 0)
    {
        close(device->fd);
    }
    free(device);
}

void *app_device_read(void *argv)
{
    unsigned char buf[1024];
    int result = 0;
    Device *device = (Device *)argv;

    while(device->running)
    {
        result = read(device->fd, buf, sizeof(buf));
        if (result <= 0)
        {
            continue;
        }
        

        if (device->funcs->post_read)
        {
            device->funcs->post_read(device, buf, &result);
            if (result <= 0)
            {
                continue;
            }
        }

        app_buffer_write(device->read_buffer, buf, result);

         // 发送task，让线程池处理后续任务
        app_pool_registerTask(app_device_sendTask, device);
    }
    return NULL;
}

void *app_device_sendTask(void *argv)
{
    log_debug("Send task start");
    Device *device = (Device *)argv;
    unsigned char buf[1024];
    app_buffer_read(device->read_buffer, buf, 2);
    app_buffer_read(device->read_buffer, buf+2, buf[0]);
    app_buffer_read(device->read_buffer, buf+2+buf[0], buf[1]);
    device->funcs->send_msg(device, buf, buf[0]+buf[1]+2);
    log_debug("Send task end");

    return NULL;
}

int app_device_recvMsg(Device *device, void *ptr, int len)
{
    // 将数据写入设备发送缓存
    int result = app_buffer_write(&device->write_buffer, ptr, len);
    if (result < 0)
    {
        log_error("app_device_recvMsg failed");
        return -1;
    }

    // 注册一个向设备写数据的任务，让线程池处理
    return app_pool_registerTask(app_device_writeTask, &device);
}

void *app_device_writeTask(void *argv)
{
    Device *device = (Device *)argv;
    unsigned char buf[1024];
    app_buffer_read(device->write_buffer, buf, 2);
    app_buffer_read(device->write_buffer, buf+2, buf[0]);
    app_buffer_read(device->write_buffer, buf+2+buf[0], buf[1]);
    int len = buf[0]+buf[1]+2;
    while (app_common_getCurrentTime() - device->last_write_time < 100)
    {
        usleep(1000);
    }
    if (device->funcs->pre_write)
    {
        device->funcs->pre_write(device, buf, &len);
    }
    if (len > 0)
    {
        write(device->fd, buf, len);
    }

    return NULL;
}
